package com.sky.Protocol;

import com.sky.Push.ClientManager;
import com.sky.Push.RequestHandler;
import com.sky.Push.Singleton;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * Created by sun on 2017-06-11.
 */
public class MessageHandler extends SimpleChannelInboundHandler<MessageProtocol> {

    private static final Logger logger = LoggerFactory.getLogger(MessageHandler.class);

    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        MessageProtocol msg = null;

        if(IdleStateEvent.class.isAssignableFrom(evt.getClass()))
        {
            IdleStateEvent event = (IdleStateEvent)evt;
            if(event.state() == IdleState.READER_IDLE)
            {
                //modify on 20170722
                msg = new MessageProtocol("ping");
                ctx.writeAndFlush(msg).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);

//                //修改心跳超时逻辑
//                //////////////////////////////////////////////////////////
//                //超时关闭连接
//                ClientManager clientManager = ClientManager.getInstance();
//                clientManager.removeClient(ctx.channel().id().asShortText());
//                ctx.close();
//
//                logger.info("client {} timeout,connection will be closed!",ctx.channel().id().asShortText());
//                //////////////////////////////////////////////////////////

            }
//            else {
//                msg = new MessageProtocol("ping");
//                ctx.writeAndFlush(msg);
//
//                System.out.println("send ping---");
//            }
        }
        else {
            //远程主机强制关闭连接
            System.out.println("remote close connection---");
            ctx.channel().close();
        }

    }

    public void channelRegistered(ChannelHandlerContext ctx) {
        ClientManager clientManager = ClientManager.getInstance();
        clientManager.addClient(ctx.channel().id().asShortText(),ctx);

        String ip = ((InetSocketAddress)ctx.channel().remoteAddress()).getAddress().getHostAddress();

        logger.info("new client {},ip {}",ctx.channel().id().asShortText(),ip);
        logger.info("client counts {}",clientManager.getClientCount());
    }

    public void channelUnregistered(ChannelHandlerContext ctx) {
        ClientManager clientManager = ClientManager.getInstance();
        clientManager.removeClient(ctx.channel().id().asShortText());
        String ip = ((InetSocketAddress)ctx.channel().remoteAddress()).getAddress().getHostAddress();
        ctx.close();
        logger.info("close client {},ip {}",ctx.channel().id().asShortText(),ip);
        logger.info("client counts {}",clientManager.getClientCount());
    }

//    public void channelRead(ChannelHandlerContext ctx,Object msg) {
//        System.out.println(((MessageProtocol)msg).getBody());
//
//        RequestHandler requestHandler = null;
//        try {
//            requestHandler = (RequestHandler)Singleton.getInstance(RequestHandler.class);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        requestHandler.handle((MessageProtocol)msg);
//        ctx.write(msg);
//
//        System.out.println(ctx.channel().id().asShortText());
//    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, MessageProtocol messageProtocol) throws Exception {

        System.out.println(messageProtocol.getBody());

        RequestHandler requestHandler = null;
        try {
            requestHandler = (RequestHandler)Singleton.getInstance(RequestHandler.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        requestHandler.handle(messageProtocol);

        if(channelHandlerContext.channel().isWritable())
        {
            channelHandlerContext.writeAndFlush(messageProtocol);
        }

    }

    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        System.out.println(cause);
        logger.info("exception caught :{}",cause.toString());
        ctx.close();
    }

}
